﻿/****************
* Authored by Zhuo "Wizcas" Chen
* 2018 © Wubi.fun all rights reserved
*****************/

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Wubi.Utils;

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class Ground : MonoBehaviour 
{
    static Ground _instance;
    public static Ground instance { get { return _instance ?? (_instance = FindObjectOfType<Ground>()); } }
    public Vector2Int dimensions;
    public float cellSize;

    MeshFilter _mf;
    MeshFilter meshFilter { get { return _mf ?? (_mf = GetComponent<MeshFilter>()); } }
    MeshRenderer _mr;
    MeshRenderer meshRenderer { get { return _mr ?? (_mr = GetComponent<MeshRenderer>()); } }

    Vector3 _offset2Center;
    
    void Awake()
    {
        //CreateGround();
        InitDimensions();
    }

    void InitDimensions(){
        float w = dimensions.x * cellSize, h = dimensions.y * cellSize;
        _offset2Center = new Vector3(w, 0, h) * -.5f;
        World.instance.SetDimension(dimensions);
    }

    [ContextMenu("Create")]
    public void CreateGround()
    {
        InitDimensions();
        int cols = dimensions.x, rows = dimensions.y;
        var cells = rows * cols;
        int vertCols = cols + 1, vertRows = rows + 1;
        var verts = new Vector3[vertCols * vertRows];
        var uvs = new Vector2[verts.Length];
        var tris = new int[cells*6];
        for(int r = 0, cellIndex = 0; r < vertRows; r++)
        {
            for(int c = 0; c < vertCols; c++)
            {
                var vi = r*vertCols + c;
                verts[vi] = new Vector3(c * cellSize, 0, r * cellSize) + _offset2Center;
                uvs[vi] = new Vector2(c / (float)cols, r / (float)rows);
                if (c < cols && r < rows) // dont make triangles for last column and row
                {
                    var viNextRow = (r + 1) * vertCols + c;
                    var ti = cellIndex++ * 6;
                    //Debug.LogFormat("ci: {0}, ti: {1}, r: {2}, c: {3}", cellIndex, ti, r, c);
                    tris[ti] = tris[ti + 4] = vi;
                    tris[ti + 3] = vi + 1;
                    tris[ti + 1] = viNextRow;
                    tris[ti + 2] = tris[ti + 5] = viNextRow + 1;
                }
            }
        }
        var mesh = meshFilter.sharedMesh;
        if (mesh == null)
        {
            mesh = new Mesh();
            meshFilter.sharedMesh = mesh;
        }
        else
            mesh.Clear();
        mesh.vertices = verts;
        mesh.uv = uvs;
        mesh.triangles = tris;
        //Debug.LogFormat("verts: {0}\nuvs: {1}\ntris:{2}", verts.Print(), uvs.Print(), tris.Print());
        mesh.RecalculateNormals();
        mesh.RecalculateTangents();
        mesh.RecalculateBounds();
        meshRenderer.sharedMaterial.SetTextureScale("_MainTex", new Vector2(cols, rows));
    }

    public CellInfo GetCellInfo(Vector3 posXZ)
    {
        var localPos = posXZ - _offset2Center;
        var col = (int)(localPos.x / cellSize);
        var row = (int)(localPos.z / cellSize);
        return new CellInfo(col, row, dimensions, cellSize, _offset2Center);
    }
    public CellInfo GetCellInfo(Vector2Int coord)
    {
        return new CellInfo(coord.x, coord.y, dimensions, cellSize, _offset2Center);
    }
}

public class CellInfo
{
    public int col;
    public int row;
    public Vector3 pos;
    public bool isInGrid { get; private set; }
    public Vector2Int coord { get { return new Vector2Int(col, row); } }
    public CellInfo(int col, int row, Vector2Int dimensions, float cellSize, Vector3 offset)
    {
        this.col = col;
        this.row = row;
        isInGrid = col >= 0 && row >= 0 && col < dimensions.x && row < dimensions.y;
        if (isInGrid)
        {
            var cellPos = cellSize * new Vector3(col, 0, row) + new Vector3(1, 0, 1) * cellSize * .5f;
            pos = cellPos + offset;
        }
        else
        {
            pos = Vector3.negativeInfinity;
        }
    }
}
